Libraries
library(tidyverse)
library(lubridate)
library(stringr)
library(ggplot2)
library(ggridges)
library(htmltools)
library(bslib)
library(plotly)
library(dplyr)
library(grDevices)
library(usmap)
library(kableExtra)
library(showtext) # <-- ADD
showtext_auto() # <-- ADD
font_add_google("Playfair Display", "playfair") # <-- ADD
shopping <- read_csv("proper_raw_shopping_behavior.csv")
shopping
Summary
This project explores shopping behavior using a dataset from Kaggle,
containing data from 3,900 U.S. shoppers. The analysis focused on
spending patterns, demographic trends, and seasonal or regional
differences in purchasing habits. The goal was to identify which groups
shop the most, which categories draw the highest spending, and how
patterns shift or differ based on location and time of year.
After exploratory data analysis was performed, clear trends appeared
such as mid-range spending, consistent seasonal fluctuations, and
noticeable imbalances in gender representation. The results offer a
broad picture of who shops, what they prefer, and where the most
activity occurs, creating a foundation for understanding customer
behavior in a simplified retail environment.
Purpose
The goal of this project was to explore how demographic and seasonal
factors influence shopping behavior. The main questions to be answered
were: Who spends the most? Which products and colors are most popular?
How do location and season affect purchase trends? This analysis helps
show how businesses might better understand consumer preferences and
plan marketing strategies.
Data
- Dataset Description & Features
The dataset came from Kaggle and contains 3,900 U.S.-based customer
records with 18 total attributes describing shopping patterns,
preferences, and demographics. This project focused on 10 of those
variables to highlight specific spending and behavioral trends rather
than analyzing every available feature.
The variables used were:
variables <- data.frame(
Variable = c("Gender", "Age", "Category", "Color", "Purchase_Amount_(USD)",
"Payment_Method", "Location", "Season"),
Type = c("Categorical", "Numeric", "Categorical", "Categorical", "Numeric",
"Categorical", "Categorical", "Categorical"),
Description_Unit = c(
"Male or Female",
"Age of customer in years",
"Product category (ex: Clothing, Footwear, etc.)",
"Product color purchased",
"Purchase amount in U.S. dollars",
"Method used for payment (Debit/Credit Card, PayPal, etc.)",
"Customer’s U.S. state",
"Season of purchase (Spring, Summer, Fall, Winter)"
)
)
kable(variables, col.names = c("Variable", "Type", "Description / Unit")) %>%
kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover")) %>%
row_spec(0, bold = TRUE, color = "#fff", background = "#cc0099")
| Variable |
Type |
Description / Unit |
| Gender |
Categorical |
Male or Female |
| Age |
Numeric |
Age of customer in years |
| Category |
Categorical |
Product category (ex: Clothing, Footwear, etc.) |
| Color |
Categorical |
Product color purchased |
| Purchase_Amount_(USD) |
Numeric |
Purchase amount in U.S. dollars |
| Payment_Method |
Categorical |
Method used for payment (Debit/Credit Card, PayPal, etc.) |
| Location |
Categorical |
Customer’s U.S. state |
| Season |
Categorical |
Season of purchase (Spring, Summer, Fall, Winter) |
These variables provided a good balance between numeric and
categorical data that helped explore spending behavior, preferences, and
demographic patterns.
Missing & Null Values There were no major missing or null
values in the dataset. The data was already clean, with complete entries
for all selected columns. Since the dataset was in good shape, there was
no need to make any corrections or fill in missing values before
analysis. This made it easier to jump straight into exploring patterns
and building visuals.
Methodology and Changes The dataset was already in a tidy format,
each row clearly represented a single purchase record and each column
represented a single attribute. tidyverse and dplyr libraries were used
for summarizing, filtering, and visualizing data. Functions like
count(), mutate(), and summarize() were also used to help create
comparisons between gender, categories, and locations.
When visualizing, the reorder() function was used with ggplot2 to
organize bars and boxplots in a more readable way. Other than that, the
dataset didn’t require any major structural changes, so the main focus
was on exploring relationships and identifying trends in spending and
shopping behavior.
Exploratory Data Analysis
a) Summary Stats & Overview
summary(shopping)
Customer ID Age Gender Item_Purchased Category
Min. : 1.0 Min. :18.00 Length:3900 Length:3900 Length:3900
1st Qu.: 975.8 1st Qu.:31.00 Class :character Class :character Class :character
Median :1950.5 Median :44.00 Mode :character Mode :character Mode :character
Mean :1950.5 Mean :44.07
3rd Qu.:2925.2 3rd Qu.:57.00
Max. :3900.0 Max. :70.00
Purchase_Amount_(USD) Location Size Color
Min. : 20.00 Length:3900 Length:3900 Length:3900
1st Qu.: 39.00 Class :character Class :character Class :character
Median : 60.00 Mode :character Mode :character Mode :character
Mean : 59.76
3rd Qu.: 81.00
Max. :100.00
Season Review_Rating Subscription_Status Shipping_Type
Length:3900 Min. :2.50 Length:3900 Length:3900
Class :character 1st Qu.:3.10 Class :character Class :character
Mode :character Median :3.70 Mode :character Mode :character
Mean :3.75
3rd Qu.:4.40
Max. :5.00
Discount_Applied Promo_Code_Used Previous_Purchases Payment_Method
Length:3900 Length:3900 Min. : 1.00 Length:3900
Class :character Class :character 1st Qu.:13.00 Class :character
Mode :character Mode :character Median :25.00 Mode :character
Mean :25.35
3rd Qu.:38.00
Max. :50.00
Frequency of Purchases
Length:3900
Class :character
Mode :character
- The summary statistics gives a quick view of the dataset’s
structure. Customer ages range from 18 to 70, with a median of 44,
showing that the data is frequently around middle-aged shoppers.
Purchase amounts range from 20 dollars to 100, with a median of 60
dollars and a mean of about $59.8, which supports the idea that most
spending falls in a steady mid-range instead of at the extreme ends.
Previous purchases show a wide distribution (1 to 50), suggesting
customers vary a lot in how frequently they shop. There is a mix of
categorical and numerical variables. Overall, the summary shows that the
dataset is complete (no missing values shown), balanced, and structured
in a way that supports a straightforward analysis.
Histogram for Age distribution 👶 👴
ggplot(shopping, aes(x = Age)) +
geom_histogram(binwidth = 5, fill = "maroon3", color = "thistle1") +
labs(
title = "Distribution of Customer Ages",
x = "Age",
y = "Count"
) +
theme(
text = element_text(family = "playfair"),
plot.title = element_text(family = "playfair", face = "bold", size = 16),
plot.subtitle = element_text(family = "playfair", size = 11),
axis.title = element_text(family = "playfair", size = 12),
axis.text = element_text(family = "playfair", size = 10),
panel.grid.minor = element_blank()
)

- This histogram shows the distribution of the ages of the customers
from the dataset. It can be seen that there are roughly two peaks, the
first around 20-30 and the second between 50 and 60. This suggests that
the main groups of shoppers are either young or old. There are fewer
middle-aged shoppers in this population.
Histogram for purchase amount distribution
🛒💲
ggplot(shopping, aes(x = `Purchase_Amount_(USD)` )) +
geom_histogram(binwidth = 5, fill = "maroon3", color = "thistle1") +
labs(
title = "Distribution of Purchase Amounts",
x = "Purchase Amount in Dollars",
y = "Number of Purchases"
) +
theme(
text = element_text(family = "playfair"),
plot.title = element_text(family = "playfair", face = "bold", size = 16),
plot.subtitle = element_text(family = "playfair", size = 11),
axis.title = element_text(family = "playfair", size = 12),
axis.text = element_text(family = "playfair", size = 10),
panel.grid.minor = element_blank()
)

- This bar chart shows the distribution of purchase amounts from the
shopping data. There’s two or three peaks, one around the 30–35 dollar
range and another near 90–95 dollars. This means that customers tend to
spend either on the lower or higher end, with fewer purchases falling in
the mid-range.
Box Plot for Purchase Amount by Product
Category
shopping %>%
ggplot(aes(x = reorder(Category, `Purchase_Amount_(USD)`, median),
y = `Purchase_Amount_(USD)`, fill = Category)) +
geom_boxplot(show.legend = FALSE, alpha = 0.6) +
coord_flip() +
labs(
title = "Purchase Amount by Product Category",
subtitle = "Outerwear and Clothing show slightly higher spending ranges.",
x = "Product Category",
y = "Purchase Amount in Dollars"
) +
theme(
text = element_text(family = "playfair"),
plot.title = element_text(family = "playfair", face = "bold", size = 16),
plot.subtitle = element_text(family = "playfair", size = 11),
axis.title = element_text(family = "playfair", size = 12),
axis.text = element_text(family = "playfair", size = 10),
panel.grid.minor = element_blank()
)

- This boxplot shows how spending looks across the main product
categories and helps analyze which areas customers spend their money on
the most. Footwear, Clothing, and Accessories all have similar median
purchase amounts, but their spreads are different, which means some
categories have more variation in what people are willing to spend.
Outerwear has the widest spread, suggesting customers either buy very
low-cost basics or pricier pieces depending on the style or season. This
visual helps support the overall goal of the project by showing which
categories have the most consistent spending and where customers tend to
shop across a wider price range.
Average Spending by Gender
shopping %>%
group_by(Gender) %>%
summarize(
avg_spending = mean(`Purchase_Amount_(USD)`, na.rm = TRUE),
total_spending = sum(`Purchase_Amount_(USD)`)
)
shopping %>%
group_by(Gender) %>%
summarize(avg_spending = mean(`Purchase_Amount_(USD)`, na.rm = TRUE)) %>%
ggplot(aes(x = Gender, y = avg_spending, fill = Gender)) +
geom_col(alpha = 0.8) +
scale_fill_manual(values = c("Female" = "#cc0099", "Male" = "lightblue")) +
labs(
title = "Average Spending by Gender",
subtitle = "Shows the mean purchase amount across all transactions.",
x = "Gender",
y = "Average Spending (USD)"
) +
theme(
text = element_text(family = "playfair"),
plot.title = element_text(family = "playfair", face = "bold", size = 16),
plot.subtitle = element_text(family = "playfair", size = 11),
axis.title = element_text(family = "playfair", size = 12),
axis.text = element_text(family = "playfair", size = 10),
legend.position = "none"
)

- Even though male customers made more total purchases, their higher
totals are mostly due to how heavily the dataset is skewed toward men.
When comparing averages instead of totals, female shoppers actually
spent slightly more per purchase. This contrast shows exactly how
important it is to look at both totals and averages together, since
totals reflect sample size while averages reflect behavior. So even
though men appear to spend more overall, women are actually just as
active (or even a bit more generous) on a per-purchase basis.
Total Spending by Gender
shopping %>%
group_by(Gender) %>%
summarize(total_spending = sum(`Purchase_Amount_(USD)`, na.rm = TRUE)) %>%
ggplot(aes(x = Gender, y = total_spending, fill = Gender)) +
geom_col(alpha = 0.8) +
scale_fill_manual(values = c("Female" = "#cc0099", "Male" = "lightblue")) +
labs(
title = "Total Spending by Gender",
subtitle = "Shows the combined purchase amount across all customers.",
x = "Gender",
y = "Total Spending (USD)"
) +
theme_minimal(base_size = 12) +
theme(
text = element_text(family = "playfair"),
plot.title = element_text(family = "playfair", face = "bold", size = 16),
plot.subtitle = element_text(family = "playfair", size = 11),
axis.title = element_text(family = "playfair", size = 12),
axis.text = element_text(family = "playfair", size = 10),
legend.position = "none"
)

- This chart compares the total amount spent by male and female
customers. Male shoppers clearly lead in total spending, but that’s
mostly because there are more of them in the dataset. Even though men
made more purchases overall, it doesn’t necessarily mean they spend more
per purchase, just that their larger numbers add up to a higher
total.
c) Product & Color Preferences
Product Category by Gender
shopping %>%
count(Gender, Category) %>%
ggplot(aes(x = Category, y = n, fill = Gender)) +
geom_col(position = "dodge", alpha = 0.7) +
scale_fill_manual(values = c("Female" = "#cc0099", "Male" = "lightblue")) +
labs(title = "Product Categories by Gender",
x = "Category", y = "Number of Purchases") +
theme(
text = element_text(family = "playfair"),
plot.title = element_text(family = "playfair", face = "bold", size = 16),
plot.subtitle = element_text(family = "playfair", size = 11),
axis.title = element_text(family = "playfair", size = 12),
axis.text = element_text(family = "playfair", size = 10),
panel.grid.minor = element_blank()
)

- This chart compares product category purchases by gender. It is
clear that the sample does not reflect the population.
Clothing and accessories are the most popular across both groups, but
males consistently make more purchases overall in every category. The
gap is very noticeable in all categories, but especially clothing and
footwear. This reflects the dataset’s imbalance, since it contains more
male entries – meaning the results noticeably show shopping behavior
within this sample rather than representing the broader population.
Top 5 Colors by Gender
color_by_gender <- shopping %>%
count(Gender, Color, name = "Occurrences") %>%
group_by(Gender) %>%
slice_max(order_by = Occurrences, n = 5)
ggplot(color_by_gender, aes(x = reorder(Color, Occurrences),
y = Occurrences, fill = Gender)) +
geom_col(position = "identity", alpha = 0.7) + #this position = "identity" part was so helpful, before the graph was so weird and the sizes of the bars were very off, but this fixed it so that they would just overlap. The problem was that the bars were trying to stay the same size even though they were overlapping.
scale_fill_manual(values = c("Female" = "#cc0099", "Male" = "lightblue")) +
labs(
title = "Top 5 Colors by Gender",
subtitle = "Transparent overlap highlights shared color preferences.",
x = "Color",
y = "Number of Purchases"
) +
theme_minimal(base_size = 12) +
theme(
text = element_text(family = "playfair"),
plot.title = element_text(family = "playfair", face = "bold", size = 16),
plot.subtitle = element_text(family = "playfair", size = 11),
axis.title = element_text(family = "playfair", size = 12),
axis.text = element_text(family = "playfair", size = 10),
legend.text = element_text(family = "playfair", size = 10),
legend.title = element_text(family = "playfair", face = "bold", size = 11),
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "top"
)

- This chart compares the top color choices between male and female
shoppers. Pink, magenta, and green are most popular among women, while
men lean toward cooler tones like teal, cyan, and silver. You’d usually
expect more overlap between the groups, but since this dataset has more
male entries overall and came significantly tidy, it likely skews the
color rankings. Even with that imbalance, yellow and olive still show up
as shared favorites across both groups, which might represent more
neutral or universally appealing tones.
Top 5 Colors by Product Category
top_colors_by_cat <- shopping %>%
count(Category, Color, name = "Occurances") %>%
group_by(Category) %>%
slice_max(order_by = Occurances, n=5)
top_colors_by_cat %>%
ggplot(aes(x = reorder(Color, Occurances),
y = Occurances,
fill = Category)) +
geom_col(show.legend = FALSE, color = "thistle1", alpha = 0.8) +
coord_flip() +
facet_wrap(~ Category, scales = "free_y") +
labs(
title = "Top 5 Colors by Product Category",
subtitle = "Most frequently purchased colors within each category.",
x = "Color",
y = "Number of Occurrences"
) +
scale_fill_manual(values = rep("#cc0099", length(unique(top_colors_by_cat$Category)))) +
theme(
text = element_text(family = "playfair"),
plot.title = element_text(family = "playfair", face = "bold", size = 16),
plot.subtitle = element_text(family = "playfair", size = 11),
axis.title = element_text(family = "playfair", size = 12),
axis.text = element_text(family = "playfair", size = 10),
panel.grid.minor = element_blank()
)

- This chart shows the five most frequently purchased colors within
each product category. Accessories lean toward neutral and earthy tones
like Olive and Gray, while Clothing includes deeper shades like Teal and
Maroon. Footwear trends toward softer colors, and Outerwear favors
cooler ones such as Blue and Violet.
d) Regional & Seasonal Trends
Top 10 Customer Locations 📍 🗺️
shopping %>%
count(Location, name = "Purchases") %>%
arrange(desc(Purchases)) %>%
slice_head(n = 10) %>%
ggplot(aes(x = reorder(Location, Purchases), y = Purchases)) +
geom_col(fill = "#cc0099") +
coord_flip() +
labs(title = "Top 10 Customer Locations by Purchase Volume",
x = "Location", y = "Number of Purchases") +
theme(
text = element_text(family = "playfair"),
plot.title = element_text(family = "playfair", face = "bold", size = 16),
plot.subtitle = element_text(family = "playfair", size = 11),
axis.title = element_text(family = "playfair", size = 12),
axis.text = element_text(family = "playfair", size = 10),
panel.grid.minor = element_blank()
)

- This bar chart shows where most customers are shopping from. Montana
and California have the most total purchases, with states like Idaho,
Illinois, and Alabama close behind. The distribution looks fairly
balanced overall, with normal variance between states that could be
because of differences in anything from population to marketing
strategies in each location.
U.S. Map (Purchase Volume by State)
# to load the font
showtext_auto()
font_add_google("Playfair Display", "playfair")
# sum the state-level purchases
state_purchases <- shopping %>%
count(Location, name = "Purchases") %>%
rename(state = Location) %>%
mutate(code = state.abb[match(state, state.name)]) # get state abbreviations
# make interactive map
us_shopping_map <- plot_geo(state_purchases, locationmode = "USA-states") %>%
add_trace(
locations = ~code,
z = ~Purchases,
text = ~paste0(
"<b>", state, "</b><br>",
Purchases, " purchases 🛍️✨💖" #this should be shown on hover
),
hoverinfo = "text",
colorscale = list(c(0, 1), c("#f8d6e0", "#cc0099")),
marker = list(line = list(color = "white", width = 1))
) %>%
colorbar(title = "Purchases") %>%
layout(
title = list(
text = "<b>Customer Purchase Volume by State</b><br><span style='font-size:12px;'>Hover to explore regional activity</span>",
font = list(family = "Playfair Display", size = 20)
),
geo = list(
scope = "usa",
projection = list(type = "albers usa"),
bgcolor = "lightblue", # background
lakecolor = "#e9f2f9",
showlakes = TRUE
),
font = list(family = "Playfair Display")
)
us_shopping_map
- This map was added as an exploratory visual to get a broad sense of
how shopping activity varies across the country. The darker pink shades
show higher purchase volume, which makes states like Montana,
California, and Illinois stand out a bit more. Even though the map is
general and only shows state-level totals, it still gets the point
across: most states have pretty steady, moderate shopping levels, with
just a few that lean higher. It was mainly included to explore overall
patterns, not to make exact or perfectly predictive geographic
results.
Total Spending by Season ☀️ ❄️ 🌷 🍂
shopping %>%
group_by(Season) %>%
summarise(total_spending = sum(`Purchase_Amount_(USD)`)) %>%
ggplot(aes(x = Season, y = total_spending, fill = Season)) +
geom_col() +
scale_fill_manual(values = c("coral", "maroon2", "gold", "lightblue")) +
labs(title = "Total Spending by Season", x = "Season", y = "Total Spending (in Dollars)") +
theme(
text = element_text(family = "playfair"),
plot.title = element_text(family = "playfair", face = "bold", size = 16),
plot.subtitle = element_text(family = "playfair", size = 11),
axis.title = element_text(family = "playfair", size = 12),
axis.text = element_text(family = "playfair", size = 10),
panel.grid.minor = element_blank()
)

- This chart shows how total spending changes across the seasons. Fall
has the highest spending overall, while Summer has the lowest. Spring
and Winter are in the middle and are fairly close to each other, leaning
more toward the higher levels seen in Fall. All together, it gives a
simple look at when shoppers tend to spend the most and least throughout
the year.
Top 5 Colors by Season
top_colors_by_season <- shopping %>%
count(Season, Color, name = "Occurrences") %>%
group_by(Season) %>%
slice_max(order_by = Occurrences, n = 5)
ggplot(top_colors_by_season, aes(x = Color, y = Occurrences, fill = Season)) +
geom_col(position = "dodge") +
facet_wrap(~Season, scales = "free_x") +
scale_fill_manual(values = c(
"Fall" = "coral",
"Spring" = "maroon2",
"Summer" = "gold",
"Winter" = "lightblue"
)) +
labs(
title = "Top 5 Colors in Each Season",
x = "Color",
y = "Occurrences"
) +
theme_minimal(base_size = 12) +
theme(
text = element_text(family = "playfair"), # apply font
plot.title = element_text(family = "playfair", face = "bold", size = 14),
plot.subtitle = element_text(family = "playfair"),
axis.title = element_text(family = "playfair"),
axis.text = element_text(family = "playfair", angle = 45, hjust = 1, size = 9),
strip.text = element_text(family = "playfair", face = "bold")
)

- This chart shows the top five colors in each season and gives a
quick feel for how shopper preferences shift throughout the year. Fall
tends to lean warm with shades like Magenta, Olive, and Orange. Spring
switches into brighter colors such as Pink and Teal. Summer has more
cool tones like Silver, Teal, and Green, while Winter brings in deeper
colors like Green, Peach, and Maroon. Overall, the color trends line up
with the general mood of each season and help show how shopper
preferences change throughout the year.
Results
For this project, the focus was on exploring the data visually to
figure out how people shop and what patterns stand out. Descriptive
statistics and graphs in ggplot2 were used to break things down by
gender, category, season, location, etc. Since the dataset was already
clean, there wasn’t much need to do data wrangling, it was mostly
grouping, summarizing, and visualizing what was already there.
This approach was best because it lets the data speak for itself.
The boxplots, bar charts, and map made it easy to find differences
between groups and find trends that might not be obvious when looking at
raw numbers. The color and shape differences in each chart also help
show group trends. The goal was to understand who’s shopping, what
they’re buying, and when and where it’s happening, and visuals helped
make that story clear.
Overall, it was found that most people spend in a steady
midrange, with digital payments like credit cards and PayPal being the
most common Men made more total purchases, but that’s mostly because
there are more male shoppers in the dataset. On average, women actually
spend slightly more per purchase. Colors like pink, teal, and yellow
stand out across both groups, and seasons like spring and fall see the
most shopping activity. States like Montana, California, and Illinois
came out on top for total purchase volume.
Conclusions
This project helped point out how all these shopping habits
connect, like how gender, location, and season can influence what people
buy and when. One limitation is that the dataset leans more male, which
affects totals and preferences, so that’s something to consider when
looking at the results. It also doesn’t include details like customer
income or store type, which would’ve helped to understand why people
spend the way they do. Another limitation is that while data can be
analyzed by season, it would be even more helpful if the data included
the exact months. That way, specific holidays or sale periods would be
shown and could be analyzed to see how more specific timing impacts
shopping behavior.
Even with those limits, the trends are really useful. The results
suggest that convenience-based payment methods dominate, mid-range
spending is typical, and purchasing patterns are fairly consistent
across seasons and geography. This may help businesses identify which
products and payment methods appeal most to online shoppers.
If this project were to be continued, next steps could include
digging into how age affects spending or whether certain product
categories are more popular with different age groups. Also, comparing
this data to real-world sales info or state populations to see how
accurate the trends are.
Overall, this project came together well and shows a clear story
about the consumers in this dataset, what they’re buying, and when and
how they’re doing it.
LS0tCnRpdGxlOiAiRGVsaXZlcmFibGUgNSIKYXV0aG9yOiAi772h4ouGy5rirZHin6HinLTvuI4gS2VsYnkgTUsgUGFsbWVyIOKctO+4juKfoeKtkcua4ouG772hIgpkYXRlOiAiTm92ZW1iZXIgOSwgMjAyNSIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIHRoZW1lOiAKICAgICAgdmVyc2lvbjogNAogICAgICBiZzogIiNmZmU2ZmYiCiAgICAgIGZnOiAiI2NjMDA5OSIKICAgICAgcHJpbWFyeTogIiM2YjJiMWEiCiAgICAgIGJhc2VfZm9udDogCiAgICAgICAgZ29vZ2xlOiAiU291cmNlIFNhbnMgUHJvIgogICAgICBoZWFkaW5nX2ZvbnQ6IAogICAgICAgIGdvb2dsZTogIlBsYXlmYWlyIERpc3BsYXkiCi0tLQoKCiMgTGlicmFyaWVzCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdncmlkZ2VzKQpsaWJyYXJ5KGh0bWx0b29scykKbGlicmFyeShic2xpYikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ3JEZXZpY2VzKQpsaWJyYXJ5KHVzbWFwKQpsaWJyYXJ5KGthYmxlRXh0cmEpCgpsaWJyYXJ5KHNob3d0ZXh0KSAgICAgIyA8LS0gQURECnNob3d0ZXh0X2F1dG8oKSAgICAgICAjIDwtLSBBREQKZm9udF9hZGRfZ29vZ2xlKCJQbGF5ZmFpciBEaXNwbGF5IiwgInBsYXlmYWlyIikgICAjIDwtLSBBREQKCgpgYGAKCmBgYHtyfQpzaG9wcGluZyA8LSByZWFkX2NzdigicHJvcGVyX3Jhd19zaG9wcGluZ19iZWhhdmlvci5jc3YiKQpzaG9wcGluZwpgYGAKCgojIFN1bW1hcnkKVGhpcyBwcm9qZWN0IGV4cGxvcmVzIHNob3BwaW5nIGJlaGF2aW9yIHVzaW5nIGEgZGF0YXNldCBmcm9tIEthZ2dsZSwgY29udGFpbmluZyBkYXRhIGZyb20gMyw5MDAgVS5TLiBzaG9wcGVycy4gVGhlIGFuYWx5c2lzIGZvY3VzZWQgb24gc3BlbmRpbmcgcGF0dGVybnMsIGRlbW9ncmFwaGljIHRyZW5kcywgYW5kIHNlYXNvbmFsIG9yIHJlZ2lvbmFsIGRpZmZlcmVuY2VzIGluIHB1cmNoYXNpbmcgaGFiaXRzLiBUaGUgZ29hbCB3YXMgdG8gaWRlbnRpZnkgd2hpY2ggZ3JvdXBzIHNob3AgdGhlIG1vc3QsIHdoaWNoIGNhdGVnb3JpZXMgZHJhdyB0aGUgaGlnaGVzdCBzcGVuZGluZywgYW5kIGhvdyBwYXR0ZXJucyBzaGlmdCBvciBkaWZmZXIgYmFzZWQgb24gbG9jYXRpb24gYW5kIHRpbWUgb2YgeWVhci4KCkFmdGVyIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgd2FzIHBlcmZvcm1lZCwgY2xlYXIgdHJlbmRzIGFwcGVhcmVkIHN1Y2ggYXMgbWlkLXJhbmdlIHNwZW5kaW5nLCBjb25zaXN0ZW50IHNlYXNvbmFsIGZsdWN0dWF0aW9ucywgYW5kIG5vdGljZWFibGUgaW1iYWxhbmNlcyBpbiBnZW5kZXIgcmVwcmVzZW50YXRpb24uIFRoZSByZXN1bHRzIG9mZmVyIGEgYnJvYWQgcGljdHVyZSBvZiB3aG8gc2hvcHMsIHdoYXQgdGhleSBwcmVmZXIsIGFuZCB3aGVyZSB0aGUgbW9zdCBhY3Rpdml0eSBvY2N1cnMsIGNyZWF0aW5nIGEgZm91bmRhdGlvbiBmb3IgdW5kZXJzdGFuZGluZyBjdXN0b21lciBiZWhhdmlvciBpbiBhIHNpbXBsaWZpZWQgcmV0YWlsIGVudmlyb25tZW50LgoKCiMgUHVycG9zZQpUaGUgZ29hbCBvZiB0aGlzIHByb2plY3Qgd2FzIHRvIGV4cGxvcmUgaG93IGRlbW9ncmFwaGljIGFuZCBzZWFzb25hbCBmYWN0b3JzIGluZmx1ZW5jZSBzaG9wcGluZyBiZWhhdmlvci4gVGhlIG1haW4gcXVlc3Rpb25zIHRvIGJlIGFuc3dlcmVkIHdlcmU6IFdobyBzcGVuZHMgdGhlIG1vc3Q/IFdoaWNoIHByb2R1Y3RzIGFuZCBjb2xvcnMgYXJlIG1vc3QgcG9wdWxhcj8gSG93IGRvIGxvY2F0aW9uIGFuZCBzZWFzb24gYWZmZWN0IHB1cmNoYXNlIHRyZW5kcz8gVGhpcyBhbmFseXNpcyBoZWxwcyBzaG93IGhvdyBidXNpbmVzc2VzIG1pZ2h0IGJldHRlciB1bmRlcnN0YW5kIGNvbnN1bWVyIHByZWZlcmVuY2VzIGFuZCBwbGFuIG1hcmtldGluZyBzdHJhdGVnaWVzLgoKIyBEYXRhCgphLiBEYXRhc2V0IERlc2NyaXB0aW9uICYgRmVhdHVyZXMKClRoZSBkYXRhc2V0IGNhbWUgZnJvbSBLYWdnbGUgYW5kIGNvbnRhaW5zIDMsOTAwIFUuUy4tYmFzZWQgY3VzdG9tZXIgcmVjb3JkcyB3aXRoIDE4IHRvdGFsIGF0dHJpYnV0ZXMgZGVzY3JpYmluZyBzaG9wcGluZyBwYXR0ZXJucywgcHJlZmVyZW5jZXMsIGFuZCBkZW1vZ3JhcGhpY3MuIFRoaXMgcHJvamVjdCBmb2N1c2VkIG9uIDEwIG9mIHRob3NlIHZhcmlhYmxlcyB0byBoaWdobGlnaHQgc3BlY2lmaWMgc3BlbmRpbmcgYW5kIGJlaGF2aW9yYWwgdHJlbmRzIHJhdGhlciB0aGFuIGFuYWx5emluZyBldmVyeSBhdmFpbGFibGUgZmVhdHVyZS4KClRoZSB2YXJpYWJsZXMgdXNlZCB3ZXJlOgpgYGB7cn0KdmFyaWFibGVzIDwtIGRhdGEuZnJhbWUoCiAgVmFyaWFibGUgPSBjKCJHZW5kZXIiLCAiQWdlIiwgIkNhdGVnb3J5IiwgIkNvbG9yIiwgIlB1cmNoYXNlX0Ftb3VudF8oVVNEKSIsCiAgICAgICAgICAgICAgICJQYXltZW50X01ldGhvZCIsICJMb2NhdGlvbiIsICJTZWFzb24iKSwKICBUeXBlID0gYygiQ2F0ZWdvcmljYWwiLCAiTnVtZXJpYyIsICJDYXRlZ29yaWNhbCIsICJDYXRlZ29yaWNhbCIsICJOdW1lcmljIiwKICAgICAgICAgICAiQ2F0ZWdvcmljYWwiLCAiQ2F0ZWdvcmljYWwiLCAiQ2F0ZWdvcmljYWwiKSwKICBEZXNjcmlwdGlvbl9Vbml0ID0gYygKICAgICJNYWxlIG9yIEZlbWFsZSIsCiAgICAiQWdlIG9mIGN1c3RvbWVyIGluIHllYXJzIiwKICAgICJQcm9kdWN0IGNhdGVnb3J5IChleDogQ2xvdGhpbmcsIEZvb3R3ZWFyLCBldGMuKSIsCiAgICAiUHJvZHVjdCBjb2xvciBwdXJjaGFzZWQiLAogICAgIlB1cmNoYXNlIGFtb3VudCBpbiBVLlMuIGRvbGxhcnMiLAogICAgIk1ldGhvZCB1c2VkIGZvciBwYXltZW50IChEZWJpdC9DcmVkaXQgQ2FyZCwgUGF5UGFsLCBldGMuKSIsCiAgICAiQ3VzdG9tZXLigJlzIFUuUy4gc3RhdGUiLAogICAgIlNlYXNvbiBvZiBwdXJjaGFzZSAoU3ByaW5nLCBTdW1tZXIsIEZhbGwsIFdpbnRlcikiCiAgKQopCgprYWJsZSh2YXJpYWJsZXMsIGNvbC5uYW1lcyA9IGMoIlZhcmlhYmxlIiwgIlR5cGUiLCAiRGVzY3JpcHRpb24gLyBVbml0IikpICU+JQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSkgJT4lCiAgcm93X3NwZWMoMCwgYm9sZCA9IFRSVUUsIGNvbG9yID0gIiNmZmYiLCBiYWNrZ3JvdW5kID0gIiNjYzAwOTkiKQpgYGAKCgpUaGVzZSB2YXJpYWJsZXMgcHJvdmlkZWQgYSBnb29kIGJhbGFuY2UgYmV0d2VlbiBudW1lcmljIGFuZCBjYXRlZ29yaWNhbCBkYXRhIHRoYXQgaGVscGVkIGV4cGxvcmUgc3BlbmRpbmcgYmVoYXZpb3IsIHByZWZlcmVuY2VzLCBhbmQgZGVtb2dyYXBoaWMgcGF0dGVybnMuCgpiLiBNaXNzaW5nICYgTnVsbCBWYWx1ZXMKVGhlcmUgd2VyZSBubyBtYWpvciBtaXNzaW5nIG9yIG51bGwgdmFsdWVzIGluIHRoZSBkYXRhc2V0LiBUaGUgZGF0YSB3YXMgYWxyZWFkeSBjbGVhbiwgd2l0aCBjb21wbGV0ZSBlbnRyaWVzIGZvciBhbGwgc2VsZWN0ZWQgY29sdW1ucy4gU2luY2UgdGhlIGRhdGFzZXQgd2FzIGluIGdvb2Qgc2hhcGUsIHRoZXJlIHdhcyBubyBuZWVkIHRvIG1ha2UgYW55IGNvcnJlY3Rpb25zIG9yIGZpbGwgaW4gbWlzc2luZyB2YWx1ZXMgYmVmb3JlIGFuYWx5c2lzLiBUaGlzIG1hZGUgaXQgZWFzaWVyIHRvIGp1bXAgc3RyYWlnaHQgaW50byBleHBsb3JpbmcgcGF0dGVybnMgYW5kIGJ1aWxkaW5nIHZpc3VhbHMuCgpjLiBNZXRob2RvbG9neSBhbmQgQ2hhbmdlcwpUaGUgZGF0YXNldCB3YXMgYWxyZWFkeSBpbiBhIHRpZHkgZm9ybWF0LCBlYWNoIHJvdyBjbGVhcmx5IHJlcHJlc2VudGVkIGEgc2luZ2xlIHB1cmNoYXNlIHJlY29yZCBhbmQgZWFjaCBjb2x1bW4gcmVwcmVzZW50ZWQgYSBzaW5nbGUgYXR0cmlidXRlLiB0aWR5dmVyc2UgYW5kIGRwbHlyIGxpYnJhcmllcyB3ZXJlIHVzZWQgZm9yIHN1bW1hcml6aW5nLCBmaWx0ZXJpbmcsIGFuZCB2aXN1YWxpemluZyBkYXRhLiBGdW5jdGlvbnMgbGlrZSBjb3VudCgpLCBtdXRhdGUoKSwgYW5kIHN1bW1hcml6ZSgpIHdlcmUgYWxzbyB1c2VkIHRvIGhlbHAgY3JlYXRlIGNvbXBhcmlzb25zIGJldHdlZW4gZ2VuZGVyLCBjYXRlZ29yaWVzLCBhbmQgbG9jYXRpb25zLgoKV2hlbiB2aXN1YWxpemluZywgdGhlIHJlb3JkZXIoKSBmdW5jdGlvbiB3YXMgdXNlZCB3aXRoIGdncGxvdDIgdG8gb3JnYW5pemUgYmFycyBhbmQgYm94cGxvdHMgaW4gYSBtb3JlIHJlYWRhYmxlIHdheS4gT3RoZXIgdGhhbiB0aGF0LCB0aGUgZGF0YXNldCBkaWRu4oCZdCByZXF1aXJlIGFueSBtYWpvciBzdHJ1Y3R1cmFsIGNoYW5nZXMsIHNvIHRoZSBtYWluIGZvY3VzIHdhcyBvbiBleHBsb3JpbmcgcmVsYXRpb25zaGlwcyBhbmQgaWRlbnRpZnlpbmcgdHJlbmRzIGluIHNwZW5kaW5nIGFuZCBzaG9wcGluZyBiZWhhdmlvci4KCiMgKipFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzKioKCiMjIGEpIFN1bW1hcnkgU3RhdHMgJiBPdmVydmlldwoKYGBge3J9CnN1bW1hcnkoc2hvcHBpbmcpCmBgYAotIFRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MgZ2l2ZXMgYSBxdWljayB2aWV3IG9mIHRoZSBkYXRhc2V0J3Mgc3RydWN0dXJlLiBDdXN0b21lciBhZ2VzIHJhbmdlIGZyb20gMTggdG8gNzAsIHdpdGggYSBtZWRpYW4gb2YgNDQsIHNob3dpbmcgdGhhdCB0aGUgZGF0YSBpcyBmcmVxdWVudGx5IGFyb3VuZCBtaWRkbGUtYWdlZCBzaG9wcGVycy4gUHVyY2hhc2UgYW1vdW50cyByYW5nZSBmcm9tIDIwIGRvbGxhcnMgdG8gMTAwLCB3aXRoIGEgbWVkaWFuIG9mIDYwIGRvbGxhcnMgYW5kIGEgbWVhbiBvZiBhYm91dCAkNTkuOCwgd2hpY2ggc3VwcG9ydHMgdGhlIGlkZWEgdGhhdCBtb3N0IHNwZW5kaW5nIGZhbGxzIGluIGEgc3RlYWR5IG1pZC1yYW5nZSBpbnN0ZWFkIG9mIGF0IHRoZSBleHRyZW1lIGVuZHMuIFByZXZpb3VzIHB1cmNoYXNlcyBzaG93IGEgd2lkZSBkaXN0cmlidXRpb24gKDEgdG8gNTApLCBzdWdnZXN0aW5nIGN1c3RvbWVycyB2YXJ5IGEgbG90IGluIGhvdyBmcmVxdWVudGx5IHRoZXkgc2hvcC4gVGhlcmUgaXMgYSBtaXggb2YgY2F0ZWdvcmljYWwgYW5kIG51bWVyaWNhbCB2YXJpYWJsZXMuIE92ZXJhbGwsIHRoZSBzdW1tYXJ5IHNob3dzIHRoYXQgdGhlIGRhdGFzZXQgaXMgY29tcGxldGUgKG5vIG1pc3NpbmcgdmFsdWVzIHNob3duKSwgYmFsYW5jZWQsIGFuZCBzdHJ1Y3R1cmVkIGluIGEgd2F5IHRoYXQgc3VwcG9ydHMgYSBzdHJhaWdodGZvcndhcmQgYW5hbHlzaXMuCgoKIyMjICoqSGlzdG9ncmFtKiogZm9yIF9BZ2UgZGlzdHJpYnV0aW9uXyDwn5G2IPCfkbQgCmBgYHtyfQpnZ3Bsb3Qoc2hvcHBpbmcsIGFlcyh4ID0gQWdlKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGZpbGwgPSAibWFyb29uMyIsIGNvbG9yID0gInRoaXN0bGUxIikgKyAKICBsYWJzKAogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEN1c3RvbWVyIEFnZXMiLCAKICAgIHggPSAiQWdlIiwgCiAgICB5ID0gIkNvdW50IgogICkgKyAgCiAgdGhlbWUoCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBmYWNlID0gImJvbGQiLCBzaXplID0gMTYpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTEpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMCksCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpCiAgKQpgYGAKLSBUaGlzIGhpc3RvZ3JhbSBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBhZ2VzIG9mIHRoZSBjdXN0b21lcnMgZnJvbSB0aGUgZGF0YXNldC4gSXQgY2FuIGJlIHNlZW4gdGhhdCB0aGVyZSBhcmUgcm91Z2hseSB0d28gcGVha3MsIHRoZSBmaXJzdCBhcm91bmQgMjAtMzAgYW5kIHRoZSBzZWNvbmQgYmV0d2VlbiA1MCBhbmQgNjAuIFRoaXMgc3VnZ2VzdHMgdGhhdCB0aGUgbWFpbiBncm91cHMgb2Ygc2hvcHBlcnMgYXJlIGVpdGhlciB5b3VuZyBvciBvbGQuIFRoZXJlIGFyZSBmZXdlciBtaWRkbGUtYWdlZCBzaG9wcGVycyBpbiB0aGlzIHBvcHVsYXRpb24uCgojIyMgKipIaXN0b2dyYW0qKiBmb3IgX3B1cmNoYXNlIGFtb3VudCBkaXN0cmlidXRpb25fIPCfm5Lwn5KyCmBgYHtyfQpnZ3Bsb3Qoc2hvcHBpbmcsIGFlcyh4ID0gYFB1cmNoYXNlX0Ftb3VudF8oVVNEKWAgKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsICBmaWxsID0gIm1hcm9vbjMiLCBjb2xvciA9ICJ0aGlzdGxlMSIpICsgCiAgbGFicygKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBQdXJjaGFzZSBBbW91bnRzIiwgCiAgICB4ID0gIlB1cmNoYXNlIEFtb3VudCBpbiBEb2xsYXJzIiwgCiAgICB5ID0gIk51bWJlciBvZiBQdXJjaGFzZXMiCiAgKSArICAKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEwKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkKICApCmBgYAotIFRoaXMgYmFyIGNoYXJ0IHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgcHVyY2hhc2UgYW1vdW50cyBmcm9tIHRoZSBzaG9wcGluZyBkYXRhLiBUaGVyZSdzIHR3byBvciB0aHJlZSBwZWFrcywgb25lIGFyb3VuZCB0aGUgMzDigJMzNSBkb2xsYXIgcmFuZ2UgYW5kIGFub3RoZXIgbmVhciA5MOKAkzk1IGRvbGxhcnMuIFRoaXMgbWVhbnMgdGhhdCBjdXN0b21lcnMgdGVuZCB0byBzcGVuZCBlaXRoZXIgb24gdGhlIGxvd2VyIG9yIGhpZ2hlciBlbmQsIHdpdGggZmV3ZXIgcHVyY2hhc2VzIGZhbGxpbmcgaW4gdGhlIG1pZC1yYW5nZS4KCiMjIyAqKkJveCBQbG90KiogZm9yIF9QdXJjaGFzZSBBbW91bnQgYnkgUHJvZHVjdCBDYXRlZ29yeV8gCgpgYGB7cn0Kc2hvcHBpbmcgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihDYXRlZ29yeSwgYFB1cmNoYXNlX0Ftb3VudF8oVVNEKWAsIG1lZGlhbiksIAogICAgICAgICAgICAgeSA9IGBQdXJjaGFzZV9BbW91bnRfKFVTRClgLCBmaWxsID0gQ2F0ZWdvcnkpKSArCiAgZ2VvbV9ib3hwbG90KHNob3cubGVnZW5kID0gRkFMU0UsIGFscGhhID0gMC42KSArCiAgY29vcmRfZmxpcCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiUHVyY2hhc2UgQW1vdW50IGJ5IFByb2R1Y3QgQ2F0ZWdvcnkiLAogICAgc3VidGl0bGUgPSAiT3V0ZXJ3ZWFyIGFuZCBDbG90aGluZyBzaG93IHNsaWdodGx5IGhpZ2hlciBzcGVuZGluZyByYW5nZXMuIiwKICAgIHggPSAiUHJvZHVjdCBDYXRlZ29yeSIsCiAgICB5ID0gIlB1cmNoYXNlIEFtb3VudCBpbiBEb2xsYXJzIgogICkgKyAKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEwKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkKICApCmBgYAotIFRoaXMgYm94cGxvdCBzaG93cyBob3cgc3BlbmRpbmcgbG9va3MgYWNyb3NzIHRoZSBtYWluIHByb2R1Y3QgY2F0ZWdvcmllcyBhbmQgaGVscHMgYW5hbHl6ZSB3aGljaCBhcmVhcyBjdXN0b21lcnMgc3BlbmQgdGhlaXIgbW9uZXkgb24gdGhlIG1vc3QuIEZvb3R3ZWFyLCBDbG90aGluZywgYW5kIEFjY2Vzc29yaWVzIGFsbCBoYXZlIHNpbWlsYXIgbWVkaWFuIHB1cmNoYXNlIGFtb3VudHMsIGJ1dCB0aGVpciBzcHJlYWRzIGFyZSBkaWZmZXJlbnQsIHdoaWNoIG1lYW5zIHNvbWUgY2F0ZWdvcmllcyBoYXZlIG1vcmUgdmFyaWF0aW9uIGluIHdoYXQgcGVvcGxlIGFyZSB3aWxsaW5nIHRvIHNwZW5kLiBPdXRlcndlYXIgaGFzIHRoZSB3aWRlc3Qgc3ByZWFkLCBzdWdnZXN0aW5nIGN1c3RvbWVycyBlaXRoZXIgYnV5IHZlcnkgbG93LWNvc3QgYmFzaWNzIG9yIHByaWNpZXIgcGllY2VzIGRlcGVuZGluZyBvbiB0aGUgc3R5bGUgb3Igc2Vhc29uLiBUaGlzIHZpc3VhbCBoZWxwcyBzdXBwb3J0IHRoZSBvdmVyYWxsIGdvYWwgb2YgdGhlIHByb2plY3QgYnkgc2hvd2luZyB3aGljaCBjYXRlZ29yaWVzIGhhdmUgdGhlIG1vc3QgY29uc2lzdGVudCBzcGVuZGluZyBhbmQgd2hlcmUgY3VzdG9tZXJzIHRlbmQgdG8gc2hvcCBhY3Jvc3MgYSB3aWRlciBwcmljZSByYW5nZS4KCgojIyBiKSBTaG9wcGluZyBCZWhhdmlvciAmIFNwZW5kaW5nIFRyZW5kcwoKIyMjIFBheW1lbnQgTWV0aG9kcyBEaXN0cmlidXRpb24gICDwn5KzIPCfkrUg8J+TsQpgYGB7cn0Kc2hvcHBpbmcgJT4lCiAgY291bnQoUGF5bWVudF9NZXRob2QpICU+JQogIG11dGF0ZShwY3QgPSBuIC8gc3VtKG4pKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKFBheW1lbnRfTWV0aG9kLCBwY3QpLCB5ID0gcGN0LCBmaWxsID0gUGF5bWVudF9NZXRob2QpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzY2FsZXM6OnBlcmNlbnQocGN0LCBhY2N1cmFjeSA9IDAuMSkpLCB2anVzdCA9IC0wLjMpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFBheW1lbnQgTWV0aG9kcyIsCiAgICBzdWJ0aXRsZSA9ICJNYWpvcml0eSBvZiBwdXJjaGFzZXMgd2VyZSBtYWRlIHZpYSBDcmVkaXQgQ2FyZCBhbmQgUGF5UGFsLiIsCiAgICB4ID0gIlBheW1lbnQgTWV0aG9kIiwKICAgIHkgPSAiU2hhcmUgb2YgVG90YWwgVHJhbnNhY3Rpb25zIgogICkgKwogIHRoZW1lKAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDExKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTApLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKYGBgCi0gVGhpcyBiYXIgY2hhcnQgc2hvd3MgdGhhdCBDcmVkaXQgQ2FyZCBhbmQgUGF5UGFsIGFyZSB0aGUgbW9zdCBjb21tb24gcGF5bWVudCBtZXRob2RzLiBCYW5rIFRyYW5zZmVyIGlzIHVzZWQgdGhlIGxlYXN0LCBsaWtlbHkgZHVlIHRvIGl0cyBzbG93ZXIgcHJvY2Vzc2luZyBhbmQgdGhlIGxhY2sgb2YgcmV3YXJkcywgYXMgY29tcGFyZWQgdG8gY3JlZGl0IGNhcmRzLiBCYW5rIHRyYW5zZmVycyBhbHNvIHRlbmQgdG8gaW52b2x2ZSBtb3JlIHN0ZXBzIGFuZCBzZWN1cml0eSBtZWFzdXJlcyB0aGFuIGRpZ2l0YWwgcGF5bWVudHMsIHNvIGl0IG1ha2VzIHNlbnNlIHRoYXQgc2hvcHBlcnMgcHJlZmVyIGZhc3Rlciwgb25lLWNsaWNrIG9wdGlvbnMgbGlrZSBQYXlQYWwgYW5kIGNyZWRpdCBjYXJkcy4KCiMjIEF2ZXJhZ2UgU3BlbmRpbmcgYnkgR2VuZGVyCmBgYHtyfQpzaG9wcGluZyAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHN1bW1hcml6ZSgKICAgIGF2Z19zcGVuZGluZyA9IG1lYW4oYFB1cmNoYXNlX0Ftb3VudF8oVVNEKWAsIG5hLnJtID0gVFJVRSksCiAgICB0b3RhbF9zcGVuZGluZyA9IHN1bShgUHVyY2hhc2VfQW1vdW50XyhVU0QpYCkKICApCgpzaG9wcGluZyAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHN1bW1hcml6ZShhdmdfc3BlbmRpbmcgPSBtZWFuKGBQdXJjaGFzZV9BbW91bnRfKFVTRClgLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBHZW5kZXIsIHkgPSBhdmdfc3BlbmRpbmcsIGZpbGwgPSBHZW5kZXIpKSArCiAgZ2VvbV9jb2woYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJGZW1hbGUiID0gIiNjYzAwOTkiLCAiTWFsZSIgPSAibGlnaHRibHVlIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiQXZlcmFnZSBTcGVuZGluZyBieSBHZW5kZXIiLAogICAgc3VidGl0bGUgPSAiU2hvd3MgdGhlIG1lYW4gcHVyY2hhc2UgYW1vdW50IGFjcm9zcyBhbGwgdHJhbnNhY3Rpb25zLiIsCiAgICB4ID0gIkdlbmRlciIsCiAgICB5ID0gIkF2ZXJhZ2UgU3BlbmRpbmcgKFVTRCkiCiAgKSArCiAgdGhlbWUoCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBmYWNlID0gImJvbGQiLCBzaXplID0gMTYpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTEpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIKICApCgpgYGAKLSBFdmVuIHRob3VnaCBtYWxlIGN1c3RvbWVycyBtYWRlIG1vcmUgdG90YWwgcHVyY2hhc2VzLCB0aGVpciBoaWdoZXIgdG90YWxzIGFyZSBtb3N0bHkgZHVlIHRvIGhvdyBoZWF2aWx5IHRoZSBkYXRhc2V0IGlzIHNrZXdlZCB0b3dhcmQgbWVuLiBXaGVuIGNvbXBhcmluZyBhdmVyYWdlcyBpbnN0ZWFkIG9mIHRvdGFscywgZmVtYWxlIHNob3BwZXJzIGFjdHVhbGx5IHNwZW50IHNsaWdodGx5IG1vcmUgcGVyIHB1cmNoYXNlLiBUaGlzIGNvbnRyYXN0IHNob3dzIGV4YWN0bHkgaG93IGltcG9ydGFudCBpdCBpcyB0byBsb29rIGF0IGJvdGggdG90YWxzIGFuZCBhdmVyYWdlcyB0b2dldGhlciwgc2luY2UgdG90YWxzIHJlZmxlY3Qgc2FtcGxlIHNpemUgd2hpbGUgYXZlcmFnZXMgcmVmbGVjdCBiZWhhdmlvci4gU28gZXZlbiB0aG91Z2ggbWVuIGFwcGVhciB0byBzcGVuZCBtb3JlIG92ZXJhbGwsIHdvbWVuIGFyZSBhY3R1YWxseSBqdXN0IGFzIGFjdGl2ZSAob3IgZXZlbiBhIGJpdCBtb3JlIGdlbmVyb3VzKSBvbiBhIHBlci1wdXJjaGFzZSBiYXNpcy4KCgojIyMgVG90YWwgU3BlbmRpbmcgYnkgR2VuZGVyCmBgYHtyfQpzaG9wcGluZyAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9zcGVuZGluZyA9IHN1bShgUHVyY2hhc2VfQW1vdW50XyhVU0QpYCwgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gR2VuZGVyLCB5ID0gdG90YWxfc3BlbmRpbmcsIGZpbGwgPSBHZW5kZXIpKSArCiAgZ2VvbV9jb2woYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJGZW1hbGUiID0gIiNjYzAwOTkiLCAiTWFsZSIgPSAibGlnaHRibHVlIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiVG90YWwgU3BlbmRpbmcgYnkgR2VuZGVyIiwKICAgIHN1YnRpdGxlID0gIlNob3dzIHRoZSBjb21iaW5lZCBwdXJjaGFzZSBhbW91bnQgYWNyb3NzIGFsbCBjdXN0b21lcnMuIiwKICAgIHggPSAiR2VuZGVyIiwKICAgIHkgPSAiVG90YWwgU3BlbmRpbmcgKFVTRCkiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgKwogIHRoZW1lKAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDExKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTApLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiCiAgKQpgYGAKLSBUaGlzIGNoYXJ0IGNvbXBhcmVzIHRoZSB0b3RhbCBhbW91bnQgc3BlbnQgYnkgbWFsZSBhbmQgZmVtYWxlIGN1c3RvbWVycy4gTWFsZSBzaG9wcGVycyBjbGVhcmx5IGxlYWQgaW4gdG90YWwgc3BlbmRpbmcsIGJ1dCB0aGF04oCZcyBtb3N0bHkgYmVjYXVzZSB0aGVyZSBhcmUgbW9yZSBvZiB0aGVtIGluIHRoZSBkYXRhc2V0LiBFdmVuIHRob3VnaCBtZW4gbWFkZSBtb3JlIHB1cmNoYXNlcyBvdmVyYWxsLCBpdCBkb2VzbuKAmXQgbmVjZXNzYXJpbHkgbWVhbiB0aGV5IHNwZW5kIG1vcmUgcGVyIHB1cmNoYXNlLCBqdXN0IHRoYXQgdGhlaXIgbGFyZ2VyIG51bWJlcnMgYWRkIHVwIHRvIGEgaGlnaGVyIHRvdGFsLgoKCiMjIGMpIFByb2R1Y3QgJiBDb2xvciBQcmVmZXJlbmNlcwoKIyMjIFByb2R1Y3QgQ2F0ZWdvcnkgYnkgR2VuZGVyCmBgYHtyfQpzaG9wcGluZyAlPiUKICBjb3VudChHZW5kZXIsIENhdGVnb3J5KSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBDYXRlZ29yeSwgeSA9IG4sIGZpbGwgPSBHZW5kZXIpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiLCBhbHBoYSA9IDAuNykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkZlbWFsZSIgPSAiI2NjMDA5OSIsICJNYWxlIiA9ICJsaWdodGJsdWUiKSkgKwogIGxhYnModGl0bGUgPSAiUHJvZHVjdCBDYXRlZ29yaWVzIGJ5IEdlbmRlciIsCiAgICAgICB4ID0gIkNhdGVnb3J5IiwgeSA9ICJOdW1iZXIgb2YgUHVyY2hhc2VzIikgKyAKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEwKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkKICApCmBgYAotIFRoaXMgY2hhcnQgY29tcGFyZXMgcHJvZHVjdCBjYXRlZ29yeSBwdXJjaGFzZXMgYnkgZ2VuZGVyLiBJdCBpcyBjbGVhciB0aGF0ICoqdGhlIHNhbXBsZSBkb2VzIG5vdCByZWZsZWN0IHRoZSBwb3B1bGF0aW9uLioqIENsb3RoaW5nIGFuZCBhY2Nlc3NvcmllcyBhcmUgdGhlIG1vc3QgcG9wdWxhciBhY3Jvc3MgYm90aCBncm91cHMsIGJ1dCBtYWxlcyBjb25zaXN0ZW50bHkgbWFrZSBtb3JlIHB1cmNoYXNlcyBvdmVyYWxsIGluIGV2ZXJ5IGNhdGVnb3J5LiBUaGUgZ2FwIGlzIHZlcnkgbm90aWNlYWJsZSBpbiBhbGwgY2F0ZWdvcmllcywgYnV0IGVzcGVjaWFsbHkgY2xvdGhpbmcgYW5kIGZvb3R3ZWFyLiBUaGlzIHJlZmxlY3RzIHRoZSBkYXRhc2V04oCZcyBpbWJhbGFuY2UsIHNpbmNlIGl0IGNvbnRhaW5zIG1vcmUgbWFsZSBlbnRyaWVzIC0tIG1lYW5pbmcgdGhlIHJlc3VsdHMgbm90aWNlYWJseSBzaG93IHNob3BwaW5nIGJlaGF2aW9yIHdpdGhpbiB0aGlzIHNhbXBsZSByYXRoZXIgdGhhbiByZXByZXNlbnRpbmcgdGhlIGJyb2FkZXIgcG9wdWxhdGlvbi4KCgojIyMgVG9wIDUgQ29sb3JzIGJ5IEdlbmRlcgpgYGB7cn0KY29sb3JfYnlfZ2VuZGVyIDwtIHNob3BwaW5nICU+JQogIGNvdW50KEdlbmRlciwgQ29sb3IsIG5hbWUgPSAiT2NjdXJyZW5jZXMiKSAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHNsaWNlX21heChvcmRlcl9ieSA9IE9jY3VycmVuY2VzLCBuID0gNSkKCmdncGxvdChjb2xvcl9ieV9nZW5kZXIsIGFlcyh4ID0gcmVvcmRlcihDb2xvciwgT2NjdXJyZW5jZXMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IE9jY3VycmVuY2VzLCBmaWxsID0gR2VuZGVyKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImlkZW50aXR5IiwgYWxwaGEgPSAwLjcpICsgI3RoaXMgcG9zaXRpb24gPSAiaWRlbnRpdHkiIHBhcnQgd2FzIHNvIGhlbHBmdWwsIGJlZm9yZSB0aGUgZ3JhcGggd2FzIHNvIHdlaXJkIGFuZCB0aGUgc2l6ZXMgb2YgdGhlIGJhcnMgd2VyZSB2ZXJ5IG9mZiwgYnV0IHRoaXMgZml4ZWQgaXQgc28gdGhhdCB0aGV5IHdvdWxkIGp1c3Qgb3ZlcmxhcC4gVGhlIHByb2JsZW0gd2FzIHRoYXQgdGhlIGJhcnMgd2VyZSB0cnlpbmcgdG8gc3RheSB0aGUgc2FtZSBzaXplIGV2ZW4gdGhvdWdoIHRoZXkgd2VyZSBvdmVybGFwcGluZy4KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJGZW1hbGUiID0gIiNjYzAwOTkiLCAiTWFsZSIgPSAibGlnaHRibHVlIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiVG9wIDUgQ29sb3JzIGJ5IEdlbmRlciIsCiAgICBzdWJ0aXRsZSA9ICJUcmFuc3BhcmVudCBvdmVybGFwIGhpZ2hsaWdodHMgc2hhcmVkIGNvbG9yIHByZWZlcmVuY2VzLiIsCiAgICB4ID0gIkNvbG9yIiwKICAgIHkgPSAiTnVtYmVyIG9mIFB1cmNoYXNlcyIKICApICsKIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpICsKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEwKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDExKSwKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIgogICkKYGBgCi0gVGhpcyBjaGFydCBjb21wYXJlcyB0aGUgdG9wIGNvbG9yIGNob2ljZXMgYmV0d2VlbiBtYWxlIGFuZCBmZW1hbGUgc2hvcHBlcnMuIFBpbmssIG1hZ2VudGEsIGFuZCBncmVlbiBhcmUgbW9zdCBwb3B1bGFyIGFtb25nIHdvbWVuLCB3aGlsZSBtZW4gbGVhbiB0b3dhcmQgY29vbGVyIHRvbmVzIGxpa2UgdGVhbCwgY3lhbiwgYW5kIHNpbHZlci4gWW914oCZZCB1c3VhbGx5IGV4cGVjdCBtb3JlIG92ZXJsYXAgYmV0d2VlbiB0aGUgZ3JvdXBzLCBidXQgc2luY2UgdGhpcyBkYXRhc2V0IGhhcyBtb3JlIG1hbGUgZW50cmllcyBvdmVyYWxsIGFuZCBjYW1lIHNpZ25pZmljYW50bHkgdGlkeSwgaXQgbGlrZWx5IHNrZXdzIHRoZSBjb2xvciByYW5raW5ncy4gRXZlbiB3aXRoIHRoYXQgaW1iYWxhbmNlLCB5ZWxsb3cgYW5kIG9saXZlIHN0aWxsIHNob3cgdXAgYXMgc2hhcmVkIGZhdm9yaXRlcyBhY3Jvc3MgYm90aCBncm91cHMsIHdoaWNoIG1pZ2h0IHJlcHJlc2VudCBtb3JlIG5ldXRyYWwgb3IgdW5pdmVyc2FsbHkgYXBwZWFsaW5nIHRvbmVzLgoKIyMjIFRvcCA1IENvbG9ycyBieSBQcm9kdWN0IENhdGVnb3J5CmBgYHtyfQp0b3BfY29sb3JzX2J5X2NhdCA8LSBzaG9wcGluZyAlPiUKICBjb3VudChDYXRlZ29yeSwgQ29sb3IsIG5hbWUgPSAiT2NjdXJhbmNlcyIpICU+JQogIGdyb3VwX2J5KENhdGVnb3J5KSAlPiUKICBzbGljZV9tYXgob3JkZXJfYnkgPSBPY2N1cmFuY2VzLCBuPTUpCgp0b3BfY29sb3JzX2J5X2NhdCAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKENvbG9yLCBPY2N1cmFuY2VzKSwgCiAgICAgICAgICAgICB5ID0gT2NjdXJhbmNlcywgCiAgICAgICAgICAgICBmaWxsID0gQ2F0ZWdvcnkpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSwgY29sb3IgPSAidGhpc3RsZTEiLCBhbHBoYSA9IDAuOCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgZmFjZXRfd3JhcCh+IENhdGVnb3J5LCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJUb3AgNSBDb2xvcnMgYnkgUHJvZHVjdCBDYXRlZ29yeSIsCiAgICBzdWJ0aXRsZSA9ICJNb3N0IGZyZXF1ZW50bHkgcHVyY2hhc2VkIGNvbG9ycyB3aXRoaW4gZWFjaCBjYXRlZ29yeS4iLAogICAgeCA9ICJDb2xvciIsCiAgICB5ID0gIk51bWJlciBvZiBPY2N1cnJlbmNlcyIKICApICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSByZXAoIiNjYzAwOTkiLCBsZW5ndGgodW5pcXVlKHRvcF9jb2xvcnNfYnlfY2F0JENhdGVnb3J5KSkpKSArIAogIHRoZW1lKAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDExKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTApLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCmBgYAotIFRoaXMgY2hhcnQgc2hvd3MgdGhlIGZpdmUgbW9zdCBmcmVxdWVudGx5IHB1cmNoYXNlZCBjb2xvcnMgd2l0aGluIGVhY2ggcHJvZHVjdCBjYXRlZ29yeS4gQWNjZXNzb3JpZXMgbGVhbiB0b3dhcmQgbmV1dHJhbCBhbmQgZWFydGh5IHRvbmVzIGxpa2UgT2xpdmUgYW5kIEdyYXksIHdoaWxlIENsb3RoaW5nIGluY2x1ZGVzIGRlZXBlciBzaGFkZXMgbGlrZSBUZWFsIGFuZCBNYXJvb24uIEZvb3R3ZWFyIHRyZW5kcyB0b3dhcmQgc29mdGVyIGNvbG9ycywgYW5kIE91dGVyd2VhciBmYXZvcnMgY29vbGVyIG9uZXMgc3VjaCBhcyBCbHVlIGFuZCBWaW9sZXQuCgojIyBkKSBSZWdpb25hbCAmIFNlYXNvbmFsIFRyZW5kcwoKIyMjIFRvcCAxMCBDdXN0b21lciBMb2NhdGlvbnMg8J+TjSDwn5e677iPCmBgYHtyfQpzaG9wcGluZyAlPiUKICBjb3VudChMb2NhdGlvbiwgbmFtZSA9ICJQdXJjaGFzZXMiKSAlPiUKICBhcnJhbmdlKGRlc2MoUHVyY2hhc2VzKSkgJT4lCiAgc2xpY2VfaGVhZChuID0gMTApICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoTG9jYXRpb24sIFB1cmNoYXNlcyksIHkgPSBQdXJjaGFzZXMpKSArCiAgZ2VvbV9jb2woZmlsbCA9ICIjY2MwMDk5IikgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh0aXRsZSA9ICJUb3AgMTAgQ3VzdG9tZXIgTG9jYXRpb25zIGJ5IFB1cmNoYXNlIFZvbHVtZSIsCiAgICAgICB4ID0gIkxvY2F0aW9uIiwgeSA9ICJOdW1iZXIgb2YgUHVyY2hhc2VzIikgKyAKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEwKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkKICApCmBgYAotIFRoaXMgYmFyIGNoYXJ0IHNob3dzIHdoZXJlIG1vc3QgY3VzdG9tZXJzIGFyZSBzaG9wcGluZyBmcm9tLiBNb250YW5hIGFuZCBDYWxpZm9ybmlhIGhhdmUgdGhlIG1vc3QgdG90YWwgcHVyY2hhc2VzLCB3aXRoIHN0YXRlcyBsaWtlIElkYWhvLCBJbGxpbm9pcywgYW5kIEFsYWJhbWEgY2xvc2UgYmVoaW5kLiBUaGUgZGlzdHJpYnV0aW9uIGxvb2tzIGZhaXJseSBiYWxhbmNlZCBvdmVyYWxsLCB3aXRoIG5vcm1hbCB2YXJpYW5jZSBiZXR3ZWVuIHN0YXRlcyB0aGF0IGNvdWxkIGJlIGJlY2F1c2Ugb2YgZGlmZmVyZW5jZXMgaW4gYW55dGhpbmcgZnJvbSBwb3B1bGF0aW9uIHRvIG1hcmtldGluZyBzdHJhdGVnaWVzIGluIGVhY2ggbG9jYXRpb24uCgojIyMgVS5TLiBNYXAgKFB1cmNoYXNlIFZvbHVtZSBieSBTdGF0ZSkKYGBge3J9CiMgdG8gbG9hZCB0aGUgZm9udApzaG93dGV4dF9hdXRvKCkKZm9udF9hZGRfZ29vZ2xlKCJQbGF5ZmFpciBEaXNwbGF5IiwgInBsYXlmYWlyIikKCiMgc3VtIHRoZSBzdGF0ZS1sZXZlbCBwdXJjaGFzZXMKc3RhdGVfcHVyY2hhc2VzIDwtIHNob3BwaW5nICU+JQogIGNvdW50KExvY2F0aW9uLCBuYW1lID0gIlB1cmNoYXNlcyIpICU+JQogIHJlbmFtZShzdGF0ZSA9IExvY2F0aW9uKSAlPiUKICBtdXRhdGUoY29kZSA9IHN0YXRlLmFiYlttYXRjaChzdGF0ZSwgc3RhdGUubmFtZSldKSAgIyBnZXQgc3RhdGUgYWJicmV2aWF0aW9ucwoKIyBtYWtlIGludGVyYWN0aXZlIG1hcAp1c19zaG9wcGluZ19tYXAgPC0gcGxvdF9nZW8oc3RhdGVfcHVyY2hhc2VzLCBsb2NhdGlvbm1vZGUgPSAiVVNBLXN0YXRlcyIpICU+JQogIGFkZF90cmFjZSgKICAgIGxvY2F0aW9ucyA9IH5jb2RlLAogICAgeiA9IH5QdXJjaGFzZXMsCiAgICB0ZXh0ID0gfnBhc3RlMCgKICAgICAgIjxiPiIsIHN0YXRlLCAiPC9iPjxicj4iLAogICAgICBQdXJjaGFzZXMsICIgcHVyY2hhc2VzIPCfm43vuI/inKjwn5KWIiAjdGhpcyBzaG91bGQgYmUgc2hvd24gb24gaG92ZXIKICAgICksCiAgICBob3ZlcmluZm8gPSAidGV4dCIsCiAgICBjb2xvcnNjYWxlID0gbGlzdChjKDAsIDEpLCBjKCIjZjhkNmUwIiwgIiNjYzAwOTkiKSksCiAgICBtYXJrZXIgPSBsaXN0KGxpbmUgPSBsaXN0KGNvbG9yID0gIndoaXRlIiwgd2lkdGggPSAxKSkKICApICU+JQogIGNvbG9yYmFyKHRpdGxlID0gIlB1cmNoYXNlcyIpICU+JQogIGxheW91dCgKICAgIHRpdGxlID0gbGlzdCgKICAgICAgdGV4dCA9ICI8Yj5DdXN0b21lciBQdXJjaGFzZSBWb2x1bWUgYnkgU3RhdGU8L2I+PGJyPjxzcGFuIHN0eWxlPSdmb250LXNpemU6MTJweDsnPkhvdmVyIHRvIGV4cGxvcmUgcmVnaW9uYWwgYWN0aXZpdHk8L3NwYW4+IiwKICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gIlBsYXlmYWlyIERpc3BsYXkiLCBzaXplID0gMjApCiAgICApLAogICAgZ2VvID0gbGlzdCgKICAgICAgc2NvcGUgPSAidXNhIiwKICAgICAgcHJvamVjdGlvbiA9IGxpc3QodHlwZSA9ICJhbGJlcnMgdXNhIiksCiAgICAgIGJnY29sb3IgPSAibGlnaHRibHVlIiwgICAgICAgICAgIyBiYWNrZ3JvdW5kCiAgICAgIGxha2Vjb2xvciA9ICIjZTlmMmY5IiwKICAgICAgc2hvd2xha2VzID0gVFJVRQogICAgKSwKICAgIGZvbnQgPSBsaXN0KGZhbWlseSA9ICJQbGF5ZmFpciBEaXNwbGF5IikKICApCgp1c19zaG9wcGluZ19tYXAKYGBgCi0gVGhpcyBtYXAgd2FzIGFkZGVkIGFzIGFuIGV4cGxvcmF0b3J5IHZpc3VhbCB0byBnZXQgYSBicm9hZCBzZW5zZSBvZiBob3cgc2hvcHBpbmcgYWN0aXZpdHkgdmFyaWVzIGFjcm9zcyB0aGUgY291bnRyeS4gVGhlIGRhcmtlciBwaW5rIHNoYWRlcyBzaG93IGhpZ2hlciBwdXJjaGFzZSB2b2x1bWUsIHdoaWNoIG1ha2VzIHN0YXRlcyBsaWtlIE1vbnRhbmEsIENhbGlmb3JuaWEsIGFuZCBJbGxpbm9pcyBzdGFuZCBvdXQgYSBiaXQgbW9yZS4gRXZlbiB0aG91Z2ggdGhlIG1hcCBpcyBnZW5lcmFsIGFuZCBvbmx5IHNob3dzIHN0YXRlLWxldmVsIHRvdGFscywgaXQgc3RpbGwgZ2V0cyB0aGUgcG9pbnQgYWNyb3NzOiBtb3N0IHN0YXRlcyBoYXZlIHByZXR0eSBzdGVhZHksIG1vZGVyYXRlIHNob3BwaW5nIGxldmVscywgd2l0aCBqdXN0IGEgZmV3IHRoYXQgbGVhbiBoaWdoZXIuIEl0IHdhcyBtYWlubHkgaW5jbHVkZWQgdG8gZXhwbG9yZSBvdmVyYWxsIHBhdHRlcm5zLCBub3QgdG8gbWFrZSBleGFjdCBvciBwZXJmZWN0bHkgcHJlZGljdGl2ZSBnZW9ncmFwaGljIHJlc3VsdHMuCgojIyMgVG90YWwgU3BlbmRpbmcgYnkgU2Vhc29uIOKYgO+4jyDinYTvuI8g8J+MtyDwn42CCgpgYGB7cn0Kc2hvcHBpbmcgJT4lCiAgZ3JvdXBfYnkoU2Vhc29uKSAlPiUKICBzdW1tYXJpc2UodG90YWxfc3BlbmRpbmcgPSBzdW0oYFB1cmNoYXNlX0Ftb3VudF8oVVNEKWApKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBTZWFzb24sIHkgPSB0b3RhbF9zcGVuZGluZywgZmlsbCA9IFNlYXNvbikpICsKICBnZW9tX2NvbCgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJjb3JhbCIsICJtYXJvb24yIiwgImdvbGQiLCAibGlnaHRibHVlIikpICsKICBsYWJzKHRpdGxlID0gIlRvdGFsIFNwZW5kaW5nIGJ5IFNlYXNvbiIsIHggPSAiU2Vhc29uIiwgeSA9ICJUb3RhbCBTcGVuZGluZyAoaW4gRG9sbGFycykiKSArIAogIHRoZW1lKAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDExKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTApLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCmBgYAotIFRoaXMgY2hhcnQgc2hvd3MgaG93IHRvdGFsIHNwZW5kaW5nIGNoYW5nZXMgYWNyb3NzIHRoZSBzZWFzb25zLiBGYWxsIGhhcyB0aGUgaGlnaGVzdCBzcGVuZGluZyBvdmVyYWxsLCB3aGlsZSBTdW1tZXIgaGFzIHRoZSBsb3dlc3QuIFNwcmluZyBhbmQgV2ludGVyIGFyZSBpbiB0aGUgbWlkZGxlIGFuZCBhcmUgZmFpcmx5IGNsb3NlIHRvIGVhY2ggb3RoZXIsIGxlYW5pbmcgbW9yZSB0b3dhcmQgdGhlIGhpZ2hlciBsZXZlbHMgc2VlbiBpbiBGYWxsLiBBbGwgdG9nZXRoZXIsIGl0IGdpdmVzIGEgc2ltcGxlIGxvb2sgYXQgd2hlbiBzaG9wcGVycyB0ZW5kIHRvIHNwZW5kIHRoZSBtb3N0IGFuZCBsZWFzdCB0aHJvdWdob3V0IHRoZSB5ZWFyLgoKCiMjIyBUb3AgNSBDb2xvcnMgYnkgU2Vhc29uCgpgYGB7cn0KdG9wX2NvbG9yc19ieV9zZWFzb24gPC0gc2hvcHBpbmcgJT4lCiAgY291bnQoU2Vhc29uLCBDb2xvciwgbmFtZSA9ICJPY2N1cnJlbmNlcyIpICU+JQogIGdyb3VwX2J5KFNlYXNvbikgJT4lCiAgc2xpY2VfbWF4KG9yZGVyX2J5ID0gT2NjdXJyZW5jZXMsIG4gPSA1KQoKZ2dwbG90KHRvcF9jb2xvcnNfYnlfc2Vhc29uLCBhZXMoeCA9IENvbG9yLCB5ID0gT2NjdXJyZW5jZXMsIGZpbGwgPSBTZWFzb24pKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgZmFjZXRfd3JhcCh+U2Vhc29uLCBzY2FsZXMgPSAiZnJlZV94IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoCiAgICAiRmFsbCIgPSAiY29yYWwiLAogICAgIlNwcmluZyIgPSAibWFyb29uMiIsCiAgICAiU3VtbWVyIiA9ICJnb2xkIiwKICAgICJXaW50ZXIiID0gImxpZ2h0Ymx1ZSIKICApKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRvcCA1IENvbG9ycyBpbiBFYWNoIFNlYXNvbiIsCiAgICB4ID0gIkNvbG9yIiwKICAgIHkgPSAiT2NjdXJyZW5jZXMiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgKwogIHRoZW1lKAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiKSwgICAgICAgICAgICAgICAgICMgYXBwbHkgZm9udAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBmYWNlID0gImJvbGQiLCBzaXplID0gMTQpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gOSksCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIGZhY2UgPSAiYm9sZCIpCiAgKQoKYGBgCi0gVGhpcyBjaGFydCBzaG93cyB0aGUgdG9wIGZpdmUgY29sb3JzIGluIGVhY2ggc2Vhc29uIGFuZCBnaXZlcyBhIHF1aWNrIGZlZWwgZm9yIGhvdyBzaG9wcGVyIHByZWZlcmVuY2VzIHNoaWZ0IHRocm91Z2hvdXQgdGhlIHllYXIuIEZhbGwgdGVuZHMgdG8gbGVhbiB3YXJtIHdpdGggc2hhZGVzIGxpa2UgTWFnZW50YSwgT2xpdmUsIGFuZCBPcmFuZ2UuIFNwcmluZyBzd2l0Y2hlcyBpbnRvIGJyaWdodGVyIGNvbG9ycyBzdWNoIGFzIFBpbmsgYW5kIFRlYWwuIFN1bW1lciBoYXMgbW9yZSBjb29sIHRvbmVzIGxpa2UgU2lsdmVyLCBUZWFsLCBhbmQgR3JlZW4sIHdoaWxlIFdpbnRlciBicmluZ3MgaW4gZGVlcGVyIGNvbG9ycyBsaWtlIEdyZWVuLCBQZWFjaCwgYW5kIE1hcm9vbi4gT3ZlcmFsbCwgdGhlIGNvbG9yIHRyZW5kcyBsaW5lIHVwIHdpdGggdGhlIGdlbmVyYWwgbW9vZCBvZiBlYWNoIHNlYXNvbiBhbmQgaGVscCBzaG93IGhvdyBzaG9wcGVyIHByZWZlcmVuY2VzIGNoYW5nZSB0aHJvdWdob3V0IHRoZSB5ZWFyLgoKCiMgUmVzdWx0cwotIEZvciB0aGlzIHByb2plY3QsIHRoZSBmb2N1cyB3YXMgb24gZXhwbG9yaW5nIHRoZSBkYXRhIHZpc3VhbGx5IHRvIGZpZ3VyZSBvdXQgaG93IHBlb3BsZSBzaG9wIGFuZCB3aGF0IHBhdHRlcm5zIHN0YW5kIG91dC4gRGVzY3JpcHRpdmUgc3RhdGlzdGljcyBhbmQgZ3JhcGhzIGluIGdncGxvdDIgd2VyZSB1c2VkIHRvIGJyZWFrIHRoaW5ncyBkb3duIGJ5IGdlbmRlciwgY2F0ZWdvcnksIHNlYXNvbiwgbG9jYXRpb24sIGV0Yy4gU2luY2UgdGhlIGRhdGFzZXQgd2FzIGFscmVhZHkgY2xlYW4sIHRoZXJlIHdhc24ndCBtdWNoIG5lZWQgdG8gZG8gZGF0YSB3cmFuZ2xpbmcsIGl0IHdhcyBtb3N0bHkgZ3JvdXBpbmcsIHN1bW1hcml6aW5nLCBhbmQgdmlzdWFsaXppbmcgd2hhdCB3YXMgYWxyZWFkeSB0aGVyZS4KCi0gVGhpcyBhcHByb2FjaCB3YXMgYmVzdCBiZWNhdXNlIGl0IGxldHMgdGhlIGRhdGEgc3BlYWsgZm9yIGl0c2VsZi4gVGhlIGJveHBsb3RzLCBiYXIgY2hhcnRzLCBhbmQgbWFwIG1hZGUgaXQgZWFzeSB0byBmaW5kIGRpZmZlcmVuY2VzIGJldHdlZW4gZ3JvdXBzIGFuZCBmaW5kIHRyZW5kcyB0aGF0IG1pZ2h0IG5vdCBiZSBvYnZpb3VzIHdoZW4gbG9va2luZyBhdCByYXcgbnVtYmVycy4gVGhlIGNvbG9yIGFuZCBzaGFwZSBkaWZmZXJlbmNlcyBpbiBlYWNoIGNoYXJ0IGFsc28gaGVscCBzaG93IGdyb3VwIHRyZW5kcy4gVGhlIGdvYWwgd2FzIHRvIHVuZGVyc3RhbmQgd2hv4oCZcyBzaG9wcGluZywgd2hhdCB0aGV54oCZcmUgYnV5aW5nLCBhbmQgd2hlbiBhbmQgd2hlcmUgaXTigJlzIGhhcHBlbmluZywgYW5kIHZpc3VhbHMgaGVscGVkIG1ha2UgdGhhdCBzdG9yeSBjbGVhci4gCgotIE92ZXJhbGwsIGl0IHdhcyBmb3VuZCB0aGF0IG1vc3QgcGVvcGxlIHNwZW5kIGluIGEgc3RlYWR5IG1pZHJhbmdlLCB3aXRoIGRpZ2l0YWwgcGF5bWVudHMgbGlrZSBjcmVkaXQgY2FyZHMgYW5kIFBheVBhbCBiZWluZyB0aGUgbW9zdCBjb21tb24gTWVuIG1hZGUgbW9yZSB0b3RhbCBwdXJjaGFzZXMsIGJ1dCB0aGF04oCZcyBtb3N0bHkgYmVjYXVzZSB0aGVyZSBhcmUgbW9yZSBtYWxlIHNob3BwZXJzIGluIHRoZSBkYXRhc2V0LiBPbiBhdmVyYWdlLCB3b21lbiBhY3R1YWxseSBzcGVuZCBzbGlnaHRseSBtb3JlIHBlciBwdXJjaGFzZS4gQ29sb3JzIGxpa2UgcGluaywgdGVhbCwgYW5kIHllbGxvdyBzdGFuZCBvdXQgYWNyb3NzIGJvdGggZ3JvdXBzLCBhbmQgc2Vhc29ucyBsaWtlIHNwcmluZyBhbmQgZmFsbCBzZWUgdGhlIG1vc3Qgc2hvcHBpbmcgYWN0aXZpdHkuIFN0YXRlcyBsaWtlIE1vbnRhbmEsIENhbGlmb3JuaWEsIGFuZCBJbGxpbm9pcyBjYW1lIG91dCBvbiB0b3AgZm9yIHRvdGFsIHB1cmNoYXNlIHZvbHVtZS4KCgoKIyBDb25jbHVzaW9ucwoKLSBUaGlzIHByb2plY3QgaGVscGVkIHBvaW50IG91dCBob3cgYWxsIHRoZXNlIHNob3BwaW5nIGhhYml0cyBjb25uZWN0LCBsaWtlIGhvdyBnZW5kZXIsIGxvY2F0aW9uLCBhbmQgc2Vhc29uIGNhbiBpbmZsdWVuY2Ugd2hhdCBwZW9wbGUgYnV5IGFuZCB3aGVuLiBPbmUgbGltaXRhdGlvbiBpcyB0aGF0IHRoZSBkYXRhc2V0IGxlYW5zIG1vcmUgbWFsZSwgd2hpY2ggYWZmZWN0cyB0b3RhbHMgYW5kIHByZWZlcmVuY2VzLCBzbyB0aGF04oCZcyBzb21ldGhpbmcgdG8gY29uc2lkZXIgd2hlbiBsb29raW5nIGF0IHRoZSByZXN1bHRzLiBJdCBhbHNvIGRvZXNu4oCZdCBpbmNsdWRlIGRldGFpbHMgbGlrZSBjdXN0b21lciBpbmNvbWUgb3Igc3RvcmUgdHlwZSwgd2hpY2ggd291bGTigJl2ZSBoZWxwZWQgdG8gdW5kZXJzdGFuZCB3aHkgcGVvcGxlIHNwZW5kIHRoZSB3YXkgdGhleSBkby4gQW5vdGhlciBsaW1pdGF0aW9uIGlzIHRoYXQgd2hpbGUgZGF0YSBjYW4gYmUgYW5hbHl6ZWQgYnkgc2Vhc29uLCBpdCB3b3VsZCBiZSBldmVuIG1vcmUgaGVscGZ1bCBpZiB0aGUgZGF0YSBpbmNsdWRlZCB0aGUgZXhhY3QgbW9udGhzLiBUaGF0IHdheSwgc3BlY2lmaWMgaG9saWRheXMgb3Igc2FsZSBwZXJpb2RzIHdvdWxkIGJlIHNob3duIGFuZCBjb3VsZCBiZSBhbmFseXplZCB0byBzZWUgaG93IG1vcmUgc3BlY2lmaWMgdGltaW5nIGltcGFjdHMgc2hvcHBpbmcgYmVoYXZpb3IuCgotIEV2ZW4gd2l0aCB0aG9zZSBsaW1pdHMsIHRoZSB0cmVuZHMgYXJlIHJlYWxseSB1c2VmdWwuIFRoZSByZXN1bHRzIHN1Z2dlc3QgdGhhdCBjb252ZW5pZW5jZS1iYXNlZCBwYXltZW50IG1ldGhvZHMgZG9taW5hdGUsIG1pZC1yYW5nZSBzcGVuZGluZyBpcyB0eXBpY2FsLCBhbmQgcHVyY2hhc2luZyBwYXR0ZXJucyBhcmUgZmFpcmx5IGNvbnNpc3RlbnQgYWNyb3NzIHNlYXNvbnMgYW5kIGdlb2dyYXBoeS4gVGhpcyBtYXkgaGVscCBidXNpbmVzc2VzIGlkZW50aWZ5IHdoaWNoIHByb2R1Y3RzIGFuZCBwYXltZW50IG1ldGhvZHMgYXBwZWFsIG1vc3QgdG8gb25saW5lIHNob3BwZXJzLgoKLSBJZiB0aGlzIHByb2plY3Qgd2VyZSB0byBiZSBjb250aW51ZWQsIG5leHQgc3RlcHMgY291bGQgaW5jbHVkZSBkaWdnaW5nIGludG8gaG93IGFnZSBhZmZlY3RzIHNwZW5kaW5nIG9yIHdoZXRoZXIgY2VydGFpbiBwcm9kdWN0IGNhdGVnb3JpZXMgYXJlIG1vcmUgcG9wdWxhciB3aXRoIGRpZmZlcmVudCBhZ2UgZ3JvdXBzLiBBbHNvLCBjb21wYXJpbmcgdGhpcyBkYXRhIHRvIHJlYWwtd29ybGQgc2FsZXMgaW5mbyBvciBzdGF0ZSBwb3B1bGF0aW9ucyB0byBzZWUgaG93IGFjY3VyYXRlIHRoZSB0cmVuZHMgYXJlLiAKLSBPdmVyYWxsLCB0aGlzIHByb2plY3QgY2FtZSB0b2dldGhlciB3ZWxsIGFuZCBzaG93cyBhIGNsZWFyIHN0b3J5IGFib3V0IHRoZSBjb25zdW1lcnMgaW4gdGhpcyBkYXRhc2V0LCB3aGF0IHRoZXkncmUgYnV5aW5nLCBhbmQgd2hlbiBhbmQgaG93IHRoZXkncmUgZG9pbmcgaXQuCgoKCiMgUmVmZXJlbmNlcwotIERhdGEgVmlzdWFsaXphdGlvbiB3aXRoIGdncGxvdDIgOiA6IENIRUFUIFNIRUVULiAtIChuLmQuKS4gUmV0cmlldmVkIE5vdmVtYmVyIDEwLCAyMDI1LCBmcm9tIGh0dHBzOi8vbGlsZS5kdWtlLmVkdS93cC1jb250ZW50L3VwbG9hZHMvMjAyMC8wNy9SX2dncGxvdDJfY2hlYXRzaGVldC5wZGYKLSBHb29nbGUgRm9udHMuIChuLmQuKS4gR29vZ2xlIEZvbnRzLiBodHRwczovL2ZvbnRzLmdvb2dsZS5jb20vc3BlY2ltZW4vUGxheWZhaXIrRGlzcGxheQotIEhhZGxleSBXaWNraGFtLiAoMjAxOSkuIGdncGxvdDI6IEVsZWdhbnQgR3JhcGhpY3MgZm9yIERhdGEgQW5hbHlzaXMuCi0gR2dwbG90Mi1Cb29rLm9yZy4gaHR0cHM6Ly9nZ3Bsb3QyLWJvb2sub3JnL0xvcmVuem8sIFAuIEQuICgyMDI1KS4gCi0gVVMgTWFwcyBJbmNsdWRpbmcgQWxhc2thIGFuZCBIYXdhaWkgW1IgcGFja2FnZSB1c21hcCB2ZXJzaW9uIDEuMC4wXS4gUi1Qcm9qZWN0Lm9yZy4gaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvcGFja2FnZT11c21hcFBhY2thZ2UgLSDigJxnZ3Bsb3Qy4oCdIFRpdGxlIENyZWF0ZSBFbGVnYW50IERhdGEgVmlzdWFsaXNhdGlvbnMgVXNpbmcgdGhlIEdyYW1tYXIgb2YgR3JhcGhpY3MuICgyMDIwKS4gaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2dncGxvdDIvZ2dwbG90Mi5wZGYgCi0gUiBmb3IgRGF0YSBTY2llbmNlICgyZSkuIChuLmQuKS4gUjRkcy5oYWRsZXkubnouIGh0dHBzOi8vcjRkcy5oYWRsZXkubnovCi0gWnViYWlyYSBNYWltb25hLiAoMjAyNSkuIFNob3BwaW5nIGJlaGF2aW91cnMgZGF0YXNldC4gS2FnZ2xlLmNvbS4gaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy96dWJhaXJhbXV0aS9zaG9wcGluZy1iZWhhdmlvdXJzLWRhdGFzZXQvZGF0YQ==